/*
 ============================================================================
 Name        : hwDaemon.cpp
 Author      : westlor
 Version     :
 Copyright   : hwsys
 Description : Hello World in C++,
 ============================================================================
 */

#include <iostream>
#include <pthread.h>
#include <stdio.h>
#include <string>
#include <string.h>
#include <stdlib.h>
#include <list>
#include <sys/time.h>
#include <chrono>
#include <dirent.h>
#include <signal.h>
#include "gpio1500a.h"
#include "alc5623.h"
#include "keyboard.h"
#include "inifile.h"

using namespace std;
using std::chrono::high_resolution_clock;
using std::chrono::milliseconds;

#define NUM_THREADS 1

Gpio_1500a *gpio;
Keyboard *keyboard;
IniFile *inifile;
// static int button_quick = 1;
// static int lightValueSaveNeed = 0;
static int powersaveResumed   = 0;
static int light_status = 1;

/* 环境变量 */
vector<string> xauth_file;

void* gpio_thread(void* args);		//gpio thread
void  volume_ctrl(int isUP, bool isPushdown);
void  light_ctrl(int isUP, bool isPushdown);
void  light_switch();
void executeCMD(const char *cmd, char *result);
#define USE_BRIGHTNESS_SHOW	1

// modify by Hans
Alc5623 *pAlc5623;
static void pwroff_handler(int signum)
{
	int ret;

	cout << "Power OFF: SIGTERM" << endl;
	if((signum == SIGTERM) && (pAlc5623 != NULL)){
		ret = pAlc5623->mute();
		if(ret < 0){
			cout << "Audio Mute Failed" << endl;
		}
		else{
			cout << "Audio Mute" << endl;\
		}
		usleep(500*1000);
		exit(0);
	}
}

int main(void) {
	int ret;
	keyboard = new Keyboard;
	ret = keyboard->keyboard_init();
	cout << "keyboard_init ret: " << ret << endl;
	/* 驱动加载 */
	//ret = system("insmod /opt/hwdaemon/hwDaemon.ko");
	//cout << "hwDaemon driver load: " << ret << endl;
	cout << "start gpio init..." << endl; /* prints Hello World!!! */
	gpio = new Gpio_1500a;
	ret = gpio->gpio_init();
	cout << "gpio_init ret: " << ret << endl;
	/* 读取配置文件 */
	inifile = new IniFile();
	inifile->initLater();
	
	/* 各个组件初始化操作 */
	cout << "start codec init..." << endl; /* prints Hello World!!! */
	Alc5623 *alc5623 = new Alc5623;
	pAlc5623 = alc5623; // modify by Hans
	ret = alc5623->codec_init();
	cout << "codec_init ret: " << ret << endl;

	/*创建线程，用于GPIO捕获 */
	pthread_t tids[NUM_THREADS];
	for(int i = 0; i < NUM_THREADS; ++i)
	{
		//参数依次是：创建的线程id，线程参数，调用的函数，传入的函数参数
		int ret = pthread_create(&tids[i], NULL, gpio_thread, NULL);
		if (ret != 0)
		{
		   cout << "pthread_create error: error_code=" << ret << endl;
		}
	}
	inifile->Travel();			//打印配置文件信息：当前亮度 亮度最大值/最小值

	cout << "Set SIGTERM" << endl;	// modify by Hans
	struct sigaction sig_usr;
	sig_usr.sa_flags = 0;
	sig_usr.sa_handler = pwroff_handler;
	sigemptyset(&sig_usr.sa_mask);
	sigaction(SIGTERM, &sig_usr, NULL);

	//等各个线程退出后，进程才结束
	pthread_exit(NULL);
	return 0;
}

/*
 * gpio 扫描线程，用于扫描键值：+/-
 * */
void* gpio_thread(void* args)
{
	static high_resolution_clock::time_point lastTime, nowTime;
	static int poweroffCount = 0;
	static int lvdsEnabled = 1; 
	long time_counts = 0;
	int input_value = 0;
	int old_value   = -1;
	int bgvalue = 255, tmp;
	bool isPowerOffDetect = false;

	lastTime = high_resolution_clock::now();
    cout << "gpio thread start！" << endl;
    while(1){
    	usleep(20*1000);		// 20ms扫描一次
    	time_counts++;

		if(isPowerOffDetect == false && time_counts > 150){
			isPowerOffDetect = true;
		}

		// 系统亮度值读取
		tmp = inifile->ReadBrightness();
		if(tmp != bgvalue){
			bgvalue = tmp; 
			inifile->SetBrightness(bgvalue);
		}

		// 按键值判断
    	input_value = gpio->getInput();
		usleep(5*1000);		// 5ms消抖
		if(input_value == gpio->getInput()){
			// if(button_quick || old_value != input_value){

    		if((input_value & VOLUME_UP) == 0){
    			volume_ctrl(1, true);
    		}else{
				volume_ctrl(1, false);
			} 

			if((input_value & VOLUME_DOWN) == 0){	
    			volume_ctrl(0, true);
    		}else{
				volume_ctrl(0, false);
			}

    		if((input_value & PANEL_SWITCH) == 0 && old_value != input_value){		// 该按键不支持长按
    			light_switch();
    		}

    		if((input_value & LIGHT_UP) == 0){
    			light_ctrl(1, true);
    		}else{
				light_ctrl(1, false);
			} 
			if((input_value & LIGHT_DOWN) == 0){
    			light_ctrl(0, true);
    		}else{
				light_ctrl(0, false);
			}

			if(isPowerOffDetect){
				if((input_value & POWEROFF_KEY) != 0){
					poweroffCount++;
					if(poweroffCount == 2){
						cout << "systemPoweroff detected: " << poweroffCount << endl;
						nowTime = high_resolution_clock::now();
						milliseconds timeInterval = std::chrono::duration_cast<milliseconds>(nowTime - lastTime);
						inifile->IncKeyCounts(POWEROFF_KEY);
						if(timeInterval.count() < 3500){					// 两次按键间隔小于3.5S
							cout << "now Poweroff!!!" << system("poweroff");
						}
						lastTime = nowTime;
					}
				}else{
					if(poweroffCount >= 2){									// 在power按键松开的时候再进行发送KEY_POWER
						keyboard->report_key(EV_KEY, KEY_POWER, 1);
						usleep(20*1000);
						keyboard->report_key(EV_KEY, KEY_POWER, 0);
					}
					poweroffCount = 0;
				}
			}
			
    		old_value = input_value;
    		// }  /*** if(button_quick || old_value != input_value){ ***/
		}
    	
    	/* 每3s写一次配置文件 */
    	// if(time_counts % 150 == 0){
		// 	if(lightValueSaveNeed){
		// 		lightValueSaveNeed = 0;
		// 		inifile->WriteINI();
		// 	}
    	// }

		/* 200ms 扫描一次 */
		if(time_counts % 15 == 0){
			if(inifile->LvdsIsEnabled()){
				if(lvdsEnabled != 1){
					lvdsEnabled  = 1;
					light_status = 1;
					inifile->SwitchLightON(true);
				}
			}else{
				if(lvdsEnabled != 0){
					lvdsEnabled  = 0;
					light_status = 0;
					powersaveResumed = 1;
					inifile->SwitchLightON(false);
				}
			}
		}
    }
}

/* 控制声音 增加/减小 */
// static high_resolution_clock::time_point lastTime_vol = high_resolution_clock::now();
inline void volume_ctrl(int isUP, bool isPushdown)
{
	// high_resolution_clock::time_point nowTime = high_resolution_clock::now();
	// milliseconds timeInterval = std::chrono::duration_cast<milliseconds>(nowTime - lastTime_vol);
	// if(timeInterval.count() < 150){
	// 	return;
	// }
	// lastTime_vol = nowTime;
	static bool up_isPushdowned = false;
	static bool do_isPushdowned = false;

	if(isUP){
		if(isPushdown){
			keyboard->report_key(EV_KEY, KEY_VOLUMEUP, 1);
			up_isPushdowned = true;
		}else{
			if(up_isPushdowned){
				up_isPushdowned = false;
				keyboard->report_key(EV_KEY, KEY_VOLUMEUP, 0);
			}
		}

		inifile->IncKeyCounts(VOLUME_UP);
	}else{
		if(isPushdown){
			keyboard->report_key(EV_KEY, KEY_VOLUMEDOWN, 1);
			do_isPushdowned = true;
		}else{
			if(do_isPushdowned){
				do_isPushdowned = false;
				keyboard->report_key(EV_KEY, KEY_VOLUMEDOWN, 0);
			}
		}
		
		inifile->IncKeyCounts(VOLUME_DOWN);
	}
}

/* 亮度增加/减小 */
// static high_resolution_clock::time_point lastTime_light = high_resolution_clock::now();
inline void light_ctrl(int isUP, bool isPushdown)
{
	// high_resolution_clock::time_point nowTime = high_resolution_clock::now();
	// milliseconds timeInterval = std::chrono::duration_cast<milliseconds>(nowTime - lastTime_light);
	// if(timeInterval.count() < 150){
	// 	return;
	// }
	// lastTime_light = nowTime;
	static bool up_isPushdowned = false;
	static bool do_isPushdowned = false;

	if(isUP){
#if	USE_BRIGHTNESS_SHOW
		if(isPushdown){
			keyboard->report_key(EV_KEY, KEY_BRIGHTNESSUP, 1);
			up_isPushdowned = true;
		}else{
			if(up_isPushdowned){
				keyboard->report_key(EV_KEY, KEY_BRIGHTNESSUP, 0);
				up_isPushdowned = false;
			}
		}
#endif
		// if(false == inifile->SetBrightnessUP()){
		// 	keyboard->report_key(EV_KEY, KEY_BRIGHTNESSUP, 1);
		// 	keyboard->report_key(EV_KEY, KEY_BRIGHTNESSUP, 0);
		// }else{
		// 	lightValueSaveNeed = true;
		// }
		inifile->IncKeyCounts(LIGHT_UP);		// 增加亮度+ 按键计数
	}else{
#if USE_BRIGHTNESS_SHOW
		if(isPushdown){
			keyboard->report_key(EV_KEY, KEY_BRIGHTNESSDOWN, 1);
			do_isPushdowned = true;
		}else{
			if(do_isPushdowned){
				keyboard->report_key(EV_KEY, KEY_BRIGHTNESSDOWN, 0);
				do_isPushdowned = false;
			}
		}
#endif
		// if(false == inifile->SetBrightnessDown()){

		// }else{
		// 	lightValueSaveNeed = true;
		// }
		inifile->IncKeyCounts(LIGHT_DOWN);		// 增加亮度- 按键计数
	}
}

inline void light_switch()
{
	if(light_status > 0){
		light_status = 0;
		inifile->SwitchLightON(false);
	}else{
		light_status = 1;
		if(powersaveResumed){
			powersaveResumed = 0;
			keyboard->report_key(EV_KEY, BTN_LEFT, 1);
			usleep(20*1000);
			keyboard->report_key(EV_KEY, BTN_LEFT, 0);
		}
		inifile->SwitchLightON(true);
	}
	inifile->IncKeyCounts(PANEL_SWITCH);
}

/* 执行cmd，获取打印信息 */
void executeCMD(const char *cmd, char *result)
{
    char buf_ps[1024];
    char ps[1024]={0};
    FILE *ptr;
    strcpy(ps, cmd);
    if((ptr=popen(ps, "r"))!=NULL)
    {
        while(fgets(buf_ps, 1024, ptr)!=NULL)
        {
           strcat(result, buf_ps);
           if(strlen(result)>1024)
               break;
        }
        pclose(ptr);
        ptr = NULL;
    }
    else
    {
        printf("popen %s error\n", ps);
    }
}